package edu.pku.sei.transformation.editor.model;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;

import edu.pku.sei.gefcommon.descriptor.annotation.EnumerationProperty;
import edu.pku.sei.gefcommon.descriptor.annotation.MethodProperty;
import edu.pku.sei.modeler.model.core.MetaModelElement;
import edu.pku.sei.modeler.model.core.MetaPackage;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.transformation.editor.internal.TransformationEditorModelRoot;
import edu.pku.sei.transformation.editor.model.constraint.ConstraintConnection;
import edu.pku.sei.transformation.editor.model.constraint.IConstrainableElement;

public class Model extends MetaModelElement implements IConstrainableElement{
	private String name;
	private MetaModel metamodel;
	private ArrayList<ConstraintConnection> constraintConnections = new ArrayList<ConstraintConnection>(); 

	@MethodProperty(catalog = "MetaModel", id = ModelPackage.TYPEDMODEL_NAME, setter = "setName", name = "name")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		String oldValue = this.name;
		this.name = name;
		firePropertyChange(ModelPackage.TYPEDMODEL_NAME, oldValue, name);
	}

	@MethodProperty(catalog = "MetaModel", id = ModelPackage.TYPEDMODEL_METAMODEL, setter = "setMetamodel", name = "metamodel")
	@EnumerationProperty(function = "getMetaModels")
	public MetaModel getMetamodel() {
		return metamodel;
	}

	public void setMetamodel(MetaModel metamodel) {
		MetaModel oldValue = this.metamodel;
		this.metamodel = metamodel;
		firePropertyChange(ModelPackage.TYPEDMODEL_METAMODEL, oldValue,
				this.metamodel);
	}

	public Object[] getMetaModels() {
		for (Object obj : this.getModel().getPackages()) {
			if (obj instanceof MetaPackage
					&& TransformationEditorModelRoot.METAMODEL_PACKAGE
							.equals(((MetaPackage) obj).getName())) {
				return ((MetaPackage) obj).getNamedElements().toArray();
			}

		}
		return new Object[] {};
	}

	@Override
	public void serialize(Element root) {
		super.serialize(root);
		XMLUtility.xmlInstance.serializeAttribute(root,
				ModelPackage.TYPEDMODEL_NAME, name);
		XMLUtility.xmlInstance.serializeNodeNotContain(root,
				ModelPackage.TYPEDMODEL_METAMODEL, metamodel);
		XMLUtility.xmlInstance.serializeNodes(root, ModelPackage.TYPEDMODEL_CONSTRAINTS, constraintConnections);
	}

	@Override
	public void deSerialize(Element root) {
		super.deSerialize(root);
		name = XMLUtility.xmlInstance.deSerializeString(root,
				ModelPackage.TYPEDMODEL_NAME);
		metamodel = (MetaModel) XMLUtility.xmlInstance
				.deSerializeNodeNotContain(root,
						ModelPackage.TYPEDMODEL_METAMODEL, this);
		constraintConnections.addAll(XMLUtility.xmlInstance.deSerializeNodes(root, ModelPackage.TYPEDMODEL_CONSTRAINTS));
	}

	@Override
	public void dynamicSet(String featureID, Object value) {
		if (ModelPackage.TYPEDMODEL_METAMODEL.equals(featureID)) {
			this.metamodel = (MetaModel) value;
		}
		super.dynamicSet(featureID, value);
	}

	@Override
	public String toString() {
		String name = "";
		if (getName() != null)
			name = getName();
		if (getMetamodel() != null)
			name = name + ":" + getMetamodel().getName();
		if ("".equals(name)) {
			name = "Model";
		}
		return name;
	}

	@Override
	public List<ConstraintConnection> getConstraintConnections() {
		return this.constraintConnections;
	}
}
